<template>
	<view
		ref="rootRef"
		class="v-menu-container"
		:class="[`v-menu-container--position--${menuPosition}`, { 'v-slide-x': slideAxis === 'x' }, { 'v-slide-y': slideAxis === 'y' }]"
		@touchstart="onTouchStart"
		@touchmove="onTouchMove"
		@touchend="onTouchEnd"
		@mousedown="onMouseDown"
		@mousemove="onMouseMove"
		@mouseup="onMouseUp"
	>
		<!-- 菜单栏 -->
		<view class="v-menu">
			<view v-for="item in menuItems" :key="item.id" :class="['menu-item', { active: activeMenuId === item.id }]" @click="handleMenuItemClick(item.id, item)">
				{{ item.title }}
			</view>
		</view>

		<!-- 内容区 -->
		<view class="menu-content">
			<template v-for="(item, index) in menuItems" :key="item.id">
				<view v-show="activeMenuId === item.id">
					<slot :name="`content-${index}`" :item="item">
					</slot>
				</view>
			</template>
		</view>
	</view>
</template>

<script lang="ts" setup>
import { ref, watch, inject, computed, getCurrentInstance, nextTick,provide } from 'vue';


interface MenuItem {
	id: string;
	title: string;
}

/* ========= props ========= */
const props = defineProps({
	menuPosition: {
		type: String,
		default: 'left',
		validator: (v: string) => ['left', 'right'].includes(v)
	},
	menuItems: {
		type: Array as () => MenuItem[],
		required: true
	},
	value: {
		type: String,
		default: ''
	},
	isSlide: {
		// 是否启用滑动
		type: Boolean,
		default: false
	},
	slideAxis: {
		// 滑动方向
		type: String as () => 'x' | 'y',
		default: 'x'
	}
});

const emit = defineEmits(['update:value', 'select']);

const config = inject<any>('config');
const activeMenuId = ref(props.value || props.menuItems[0]?.id || '');

/* ========= 滑动核心 ========= */
const rootRef = ref<HTMLElement>();
const startX = ref(0);
const startY = ref(0);
const isTracking = ref(false);
const SLIDE_THRESHOLD = 50;

const currentIndex = computed(() => props.menuItems.findIndex((item) => item.id === activeMenuId.value));

const next = () => {
	const len = props.menuItems.length;
	const idx = (currentIndex.value + 1 + len) % len;
	handleMenuItemClick(props.menuItems[idx].id, props.menuItems[idx]);
};

const prev = () => {
	const len = props.menuItems.length;
	const idx = (currentIndex.value - 1 + len) % len;
	handleMenuItemClick(props.menuItems[idx].id, props.menuItems[idx]);
};

const handleMenuItemClick = (id: string, row: MenuItem) => {
	activeMenuId.value = id;
	emit('update:value', id);
	emit('select', id, row);
};

/* 统一手势处理 */
const onStart = (x: number, y: number) => {
	if (!props.isSlide) return;
	startX.value = x;
	startY.value = y;
	isTracking.value = true;
};

const onMove = (x: number, y: number) => {
	if (!isTracking.value) return;
	const dx = x - startX.value;
	const dy = y - startY.value;
	const dir = props.slideAxis === 'x' ? dx : dy;
	const orth = props.slideAxis === 'x' ? dy : dx;
	if (Math.abs(orth) > Math.abs(dir)) return; // 优先同轴
};

const onEnd = (x: number, y: number) => {
	if (!isTracking.value) return;
	isTracking.value = false;
	const delta = props.slideAxis === 'x' ? x - startX.value : y - startY.value;
	if (delta > SLIDE_THRESHOLD) prev();
	else if (delta < -SLIDE_THRESHOLD) next();
};

/* Touch 事件 */
const onTouchStart = (e: TouchEvent) => onStart(e.touches[0].clientX, e.touches[0].clientY);

const onTouchMove = (e: TouchEvent) => {
	if (!props.isSlide) return;
	onMove(e.touches[0].clientX, e.touches[0].clientY);
	e.preventDefault?.();
};

const onTouchEnd = (e: TouchEvent) => onEnd(e.changedTouches[0].clientX, e.changedTouches[0].clientY);

/* Mouse 事件（PC H5） */
const onMouseDown = (e: MouseEvent) => onStart(e.clientX, e.clientY);
const onMouseMove = (e: MouseEvent) => {
	if (!isTracking.value) return;
	onMove(e.clientX, e.clientY);
	e.preventDefault?.();
};
const onMouseUp = (e: MouseEvent) => onEnd(e.clientX, e.clientY);

/* 监听 v-model 外部更新 */
watch(
	() => props.value,
	(newVal) => {
		if (newVal && newVal !== activeMenuId.value) {
			activeMenuId.value = newVal;
		}
	}
);

/* H5：禁止横向/纵向滚动冲突 */
const isH5 = typeof plus === 'undefined';
if (isH5) {
	nextTick(() => {
		const el = (getCurrentInstance()?.proxy as any)?.$el as HTMLElement;
		if (el) {
			el.style.overscrollBehaviorX = props.slideAxis === 'x' ? 'contain' : 'auto';
			el.style.overscrollBehaviorY = props.slideAxis === 'y' ? 'contain' : 'auto';
		}
	});
}
</script>

<style lang="scss" scoped>
.v-menu-container {
	display: flex;
	width: 100%;
	height: 100%;
	touch-action: pan-y; /* 允许垂直滚动，水平自己接管 */



	&--position--right {
		flex-direction: row-reverse;
	}
}

.v-menu {
	display: flex;
	flex-direction: column;
	background-color: v-bind('config.VMenu.backgroundColor');
	border-right: 1rpx solid v-bind('config.border.color');
	width: 200rpx;
	height: 100%;
	overflow-y: auto;
	transition: all 0.3s ease;
	border-radius: 6rpx 0 0 6rpx;
}

.menu-item {
	padding: 12rpx 16rpx;
	cursor: pointer;
	color: v-bind('config.fontColor.subTitle');
	transition: all 0.2s ease;
	border-bottom: 1rpx solid transparent;

	&:hover {
		background-color: v-bind('config.VMenu.highlightBackgroundColor');
	}

	&.active {
		background-color: v-bind('config.VMenu.highlightBackgroundColor');
		color: v-bind('config.fontColor.mainText');
		font-weight: bold;
		border-left: 6rpx solid v-bind('config.border.color');
	}
}

.menu-content {
	flex: 1;
	padding: 16rpx;
	background-color: v-bind('config.VMenu.reversal');
	min-height: 600rpx;
	overflow: auto;
	box-shadow: -2rpx 0 5px rgba(0, 0, 0, 0.05);
}

</style>
